package com.lvmama.config;

import com.lvmama.config.common.ZooKeeperConfigProperties;
import com.lvmama.config.factory.ZooKeeperClientFactory;
import com.lvmama.config.watcher.ZooKeeperCuratorWatcher;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.List;
import java.util.Properties;

import com.lvmama.config.common.Constant;
import org.apache.curator.framework.api.CuratorWatcher;

/**
 * Created by troy on 2016/7/19.
 * kouhongyu@163.com
 */
public class ZooKeeperConfigInit {

    public Properties getProperties(Properties props) throws Exception {

        initBase(props);
        Properties properties = new Properties();
        CuratorFramework curator = ZooKeeperClientFactory.getInstance(Constant.zookeeperConfigAddress, Constant.NAME_SPACE);
        CuratorWatcher curatorWatcher = new ZooKeeperCuratorWatcher();
        /**
         * 先加载公共配置,再加载项目本身的配置
         */
        String[] names = {"common", Constant.applicationName};

        for (String name : names) {
            String appPath = Constant.SEPARATOR + Constant.PROPERTIES +
                    Constant.SEPARATOR + Constant.zookeeperConfigOwner +
                    Constant.SEPARATOR + name;

            if (curator.checkExists().forPath(appPath) != null) {
                List<String> childrenPathList = curator.getChildren().forPath(appPath);
                if (childrenPathList != null) {

                    for (String childrenPath : childrenPathList) {
                        childrenPath = appPath + Constant.SEPARATOR + childrenPath;
                        List<String> propPathList = curator.getChildren().forPath(childrenPath);
                        if (propPathList != null) {

                            for (String propName : propPathList) {
                                String propPath = childrenPath + Constant.SEPARATOR + propName;
                                String propValue = "";
                                if (curator.checkExists().forPath(propPath) != null) {
                                    /**
                                     * 加载本机重写path
                                     */
                                    propPath = overridePath(curator, propPath);

                                    byte[] data = curator.getData().usingWatcher(curatorWatcher).forPath(propPath);
                                    propValue = data == null ? "" : new String(data, Constant.UTF_8);
                                }
                                properties.put(propName, propValue);
                                /**
                                 * 保存到 properties 池中
                                 */
                                ZooKeeperConfigProperties.putProperties(propPath,propName,propValue);
                            }
                        }
                    }
                }
            }
        }
        return properties;
    }

    private String overridePath(CuratorFramework curator, String propPath) throws Exception {
        /**
         * 重写path
         */
        String overridePath = propPath +
                Constant.SEPARATOR + Constant.OVERRIDE +
                Constant.SEPARATOR + Constant.localIp;

        if (curator.checkExists().forPath(overridePath) != null) {
            /**
             * 重写禁用path
             */
            String disabledPath = overridePath +
                    Constant.SEPARATOR + Constant.DISABLED;

            if (curator.checkExists().forPath(disabledPath) == null) {
                return overridePath;
            }
        }
        return propPath;
    }

    private void initBase(Properties props) {
        Constant.zookeeperConfigAddress = props.getProperty(Constant.ZOOKEEPER_CONFIG_ADDRESS);
        Constant.zookeeperConfigOwner = props.getProperty(Constant.ZOOKEEPER_CONFIG_OWNER);
        Constant.applicationName = props.getProperty(Constant.APPLICATION_NAME);
//        Constant.watcherEnabled = Boolean.valueOf(props.getProperty(Constant.WATCHER_ENABLED));

        bindLocalIp(Constant.zookeeperConfigAddress);
    }

    private void bindLocalIp(String zookeeperAddress) {

        String[] addressArr = StringUtils.split(zookeeperAddress, ',');
        for (String address : addressArr) {
            String[] ipAndProt = StringUtils.split(address, ":");
            String ip = ipAndProt[0];
            String port = ipAndProt[1];
            Socket socket = new Socket();

            try {
                InetSocketAddress contextPath = new InetSocketAddress(ip, Integer.parseInt(port));
                socket.connect(contextPath, 1000);
                Constant.localIp = socket.getLocalAddress().getHostAddress();
                break;
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
